package rs.etf.kdp.server;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

import javax.swing.JTextArea;

import rs.etf.kdp.client.Job;

public class ConnectionWithClient extends Thread {
	
	ObjectInputStream input;
	ObjectOutputStream output;
	InterthreadBuffer buffer;
	CurrentSimulations currentSim;
	JobManager manager;
	JTextArea status;
	Heartbeater hb;
	
	public ConnectionWithClient(ObjectInputStream input, ObjectOutputStream output, CurrentSimulations sim, JobManager manager, JTextArea status, Heartbeater hb) {
		this.input = input;
		this.output = output;
		this.buffer = new InterthreadBuffer();
		currentSim = sim;
		this.status = status;
		this.manager = manager;
		this.hb = hb;
	}
	
	public void run()
	{
//		String client = waitForClient(input);
//		if(client==null) return;
//		if(client.equals("new job"))
//		{
//			sendID(output);
//			Job job = recieveJob(input);
//			Log.changedState(job.getServerID(), "READY");
//			sendRecievedJobAck(output);
//			manager.setJob(job);
//			NewConnectionsListener.jobManagerPool.submit(manager);
//		}
		
		
		while(!interrupted())
		{
			String msg = null;
			
			try {
				msg = (String)input.readObject();
			} catch (Exception e) {
				System.out.println("Unable to recieve msg in ConnectionWithClient");
				return;
			}
			if(msg.equals("new job"))
			{
				sendID(output);
				Job job = recieveJob(input);
				Log.changedState(job.getServerID(), "READY");
				//sendRecievedJobAck(output);
				manager = new JobManager(job, status, input, output,hb);
				//manager.setJob(job);
				//NewConnectionsListener.jobManagerPool.submit(manager);
				//manager.setDaemon(true);
				manager.start();
			}
			else if(msg.startsWith("client abort"))
			{
				EventFromWS e = new EventFromWS(null, msg);
				buffer.putEventFromWS(e);
			} else if (msg.startsWith("status"))
			{
				String status;
				String[] tok = msg.split(" ");
				long id = Long.parseLong(tok[1]);
				status = currentSim.getAnySimulationStatusById(id);
				if(status==null)
				{
					status = "Simulation is not in list of simulations on server. Try again";
				}
				try {
					output.writeObject("status " + tok[1]);
					output.writeObject(status);
				} catch (IOException e) {
					System.out.println("\nUnable to send current status message to client");
				}
			} else if(msg.startsWith("oldjob"))
			{
				String[] tok = msg.split(" ");
				long id = Long.parseLong(tok[1]);
				Simulation simT = currentSim.getAnySimulationById(id);
				if(simT==null)
				{
					try {
						output.writeObject("old fail");
						output.writeObject("There is no simulation results for id " + id + " on server. When server is restarted objects that store results are deleted");
					} catch (IOException e) {
						System.out.println("Unable to send answer about missing result");
					}
					
				} else 
				{
					synchronized (manager)
					{
						Result res = simT.getResults();
						String message = "result " + id;
						
						try {
							output.writeObject(message);
							output.writeObject(res);
						} catch (IOException e) {
							System.out.println("Unable to send requested previous job");
						}
					}
				}
			}
		}
	}

	public ObjectInputStream getInput() {
		return input;
	}

	public void setInput(ObjectInputStream input) {
		this.input = input;
	}

	public ObjectOutputStream getOutput() {
		return output;
	}

	public void setOutput(ObjectOutputStream output) {
		this.output = output;
	}

	public InterthreadBuffer getBuffer() {
		return buffer;
	}

	public void setBuffer(InterthreadBuffer buffer) {
		this.buffer = buffer;
	}
	
//	private String waitForClient(ObjectInputStream input)
//	{
//		String receive = null;
//		
//		try {
//			receive = (String)input.readObject();
//		} catch (Exception e) {
//			status.append("\nError while waiting for client answer");
//		} 
//		
//		return receive;
//	}
	
	private long sendID(ObjectOutputStream output)
	{
		long jobId = NewConnectionsListener._id++;
		String idForClient = Long.toString(jobId);
		try {
			output.writeObject("jobid from server");
			output.writeObject(idForClient);
		} catch (IOException e) {
			status.append("\nError while sending job id");
		}
		
		return jobId;
	}
	
	private Job recieveJob(ObjectInputStream input)
	{
		Job job = null;
		try {
			job = (Job)input.readObject();
		} catch (IOException e) {
			status.append("\nError while recieving job");
		} catch (ClassNotFoundException e) {
			status.append("\nClassNotFound while recieving job");
		}
		
		return job;
	}
	
//	private void sendRecievedJobAck(ObjectOutputStream output)
//	{
//		String command = "jobrecieved";
//		try {
//			output.writeObject(command);
//		} catch (IOException e) {
//			status.append("\nError while recieved job confirmation");
//		}
//	}
	
	
}
